<template>
	<div
		:class="[
			'app-editor-container',
			'app-mob-file-upload',
			`app-mob-file-upload-${name}`,
		]"
	>
		<div
			v-if="isFile && showFileList && fileList.length > 0"
			class="app-mob-file-upload__filelist-container"
		>
			<span
				v-for="(file, index) in fileList"
				:key="file.id"
				class="app-mob-file-upload__filelist-item"
			>
				<a href="javascript:void(0)" @click="downLoadFile(file)">{{
					file.name
				}}</a>
				<van-icon name="delete" @click="deleteFileListitem(index)"></van-icon>
			</span>
		</div>
		<van-uploader
			v-bind="$attrs"
			v-model="fileList"
			:readonly="isRaw ? true : false"
			:class="{ 'is-picture-raw--hidden': isPictureRaw }"
			:deletable="isRaw ? false : true"
			:preview-image="isFile ? false : true"
			:multiple="multiple"
			:after-read="uploadFile"
			@delete="deleteFile"
			@click-preview="onPreview"
		>
			<template #default>
				<app-button v-if="isFile" icon="plus" type="primary" size="mini">{{
					tooltip ? tooltip : $t('common.fileupload.uptooltip', '上传文件')
				}}</app-button>
				<div v-else class="app-mob-file-upload__image-uploded">
					<van-icon name="photograph" />
				</div>
			</template>
		</van-uploader>
	</div>
</template>
<script lang="ts" setup>
import { Ref } from 'vue';
import { calcFilemime, computedNavData, IEvent, IParam } from '@/core';
import { fileUploadProps } from './file-upload';
import {
	getDownloadUrl,
	getRequestingHeader,
	getUploadUrl,
	useEditorTypeParams,
} from '@/hooks/use-editor';
import { Http } from '@/http/http';
import { typeOf } from 'qx-util';
interface EditorEmit {
	(name: 'editor-event', value: IEvent<string>): void;
}
const props = defineProps(fileUploadProps);
const emit = defineEmits<EditorEmit>();
// 类型校验
const {
	validateConfig,
	valueType,
	objectIdField,
	objectValueField,
	objectNameField,
} = useEditorTypeParams();
validateConfig();
const fileList: Ref<any> = ref([]);
let uploadUrl = ''; //上传路径
let upload_params: IParam = reactive({}); //文件上传参数
let export_params: IParam = reactive({}); // 文件下载参数

const isPictureRaw = computed(() => {
	if (props.isRaw && !props.value) {
		return true;
	}
	return false;
});

//生命周期，初始化组件数据
onBeforeMount(() => {
	handleBaseParams();
	handleUploadUrlParams();
});

//上传文件
const uploadFile = (file: any) => {
	const headerConfig = getRequestingHeader();
	const config = Object.assign({}, headerConfig, {
		'Content-Type': 'multipart/form-data',
	});
	let tempFile = [];
	if (file instanceof Array == !true) {
		tempFile.push(file);
	} else {
		tempFile = file;
	}
	const tempFiles: any[] = [];
	tempFile.forEach(async (_file: any, index: number) => {
		const formData = new FormData();
		formData.append('file', _file.file, _file.file.name);
		try {
			const response: any = await Http.getHttp()({
				method: props.method,
				url: uploadUrl,
				data: formData,
				headers: config,
			});
			if (response.success) {
				const data = response.data;
				_file.name = data.filename;
				_file.id = data.fileid;
				const filetype = calcFilemime(data.ext);
				_file.isImage = isImage(filetype);
				tempFiles.push({ name: data.filename, id: data.fileid });
				if (index + 1 == tempFile.length) {
					onSuccess(tempFiles);
				}
			}
		} catch (error) {
			_file.status = 'failed';
			App.getNotificationHelper().error(
				App.ts('common.fileupload.error', '上传失败')
			);
		}
	});
};

//文件预览
const onPreview = (file: any) => {
	if (file.isImage) {
		return;
	} else {
		//其他类型文件，询问是否下载
		downLoadFile(file);
	}
};

//文件上传列表展示类型手动删除文件
const deleteFileListitem = (index: number) => {
	fileList.value.splice(index, 1);
	deleteFile();
};

//删除文件
const deleteFile = () => {
	const data: any[] = [];
	fileList.value.forEach((item: any) => {
		const { name, id } = item;
		data.push({ name: name, id: id });
	});
	doEditorEmit(data);
};

//上传成功--抛出值
const onSuccess = (data: any) => {
	if (!data) {
		return;
	}
	let arr: Array<any> = [];
	if (props.value) {
		try {
			if (Array.isArray(props.value)) {
				const tempFileList = props.value.map((item: any) => {
					return {
						id: item[objectIdField || 'id'],
						name: item[objectNameField || 'name'],
					};
				});
				arr = tempFileList;
			} else if (typeof props.value === 'string') {
				const value = JSON.parse(props.value);
				arr = value;
			}
		} catch {
			arr = [];
		}
	}
	arr.push(...data);
	doEditorEmit(arr);
};

//统一抛出事件
const doEditorEmit = (items: any[]) => {
	let result: any = JSON.stringify(items);
	if (valueType === 'OBJECTS' || valueType === 'OBJECT') {
		const data = items.map((item: any) => {
			return {
				[objectIdField || 'id']: item.id,
				[objectNameField || 'name']: item.name,
				[objectValueField || 'value']: item,
			};
		});
		if (props.multiple) {
			result = data;
		} else if (data.length > 0) {
			result = data[0];
		}
	}
	emit('editor-event', {
		name: `${props.name}`,
		action: 'valueChange',
		data: result,
	});
};

//处理上传和下载基础参数
const handleBaseParams = () => {
	const { uploadParams, exportParams, viewParams, context } = props;
	const up_params =
		Object.keys(uploadParams).length > 0
			? JSON.parse(JSON.stringify(uploadParams))
			: {};
	const ex_params =
		Object.keys(exportParams).length > 0
			? JSON.parse(JSON.stringify(exportParams))
			: {};
	let _data: any = JSON.parse(JSON.stringify(props.data));
	//计算上传参数
	if (up_params && Object.keys(up_params).length > 0) {
		upload_params = computedNavData(_data, viewParams, context, up_params);
	}
	//计算下载参数
	if (ex_params && Object.keys(ex_params).length > 0) {
		export_params = computedNavData(_data, viewParams, context, ex_params);
	}
};

//处理上传路径
const handleUploadUrlParams = () => {
	const tempUrl = getUploadUrl();
	uploadUrl = formatUrlParam(tempUrl, upload_params);
};

//处理下载、显示地址
const handleExportUrlParams = (data: any[]) => {
	
	if (!fileList.value || fileList.value.length == 0) {
		// 值回显
		fileList.value = [];
		if (data && data.length > 0) {
			if (props.isFile) {
				//文件列表
				fileList.value = data;
			} else {
				data.forEach(async (item: any) => {
					handleFileLoad(item)
				});
			}
		}
	} else {
		//值变更
		fileList.value = fileList.value.filter((item:any)=>{
			const _index = data.findIndex((_item:any)=>{
				return _item.id == item.id
			})
			return _index >= 0;
		})
		data.forEach(async (item:any)=>{
			const index = fileList.value.findIndex((_item:any)=>{
				return _item.id == item.id;
			})
			if(index<0){
				handleFileLoad(item)
			}
		})

	}
};

//处理文件加载
const handleFileLoad = async (item:any) => {
	const tempUrl = getDownloadUrl();
	let url = `${tempUrl}/${item.id}`;
	item.url = formatUrlParam(url, export_params);
	const tempFile = await getFile(item);
	fileList.value.push(tempFile);
}

//获取后台文件流
const getFile = async (file: any): Promise<any> => {
	const tempFile = JSON.parse(JSON.stringify(file));
	try {
		const response = await Http.getHttp()({
			method: 'get',
			url: tempFile.url,
			responseType: 'blob',
		});
		if (
			!response ||
			(response.hasOwnProperty('status') && response.status != 200) ||
			(response.hasOwnProperty('success') && (response as any).success == false)
		) {
			App.getNotificationHelper().warning(
				App.ts('common.fileupload.loadfail', '加载失败')
			);
			return;
		}
		// 请求成功，后台返回的是一个文件流
		if (response.data) {
			// 获取文件名
			const filename = tempFile.name;
			const ext = '.' + filename.split('.').pop();
			let filetype = calcFilemime(ext);
			// 用blob对象获取文件流
			let blob = new Blob([response.data], { type: filetype });
			tempFile.isImage = isImage(filetype);
			if (tempFile.isImage) {
				let fileReader = new FileReader();
				return new Promise((resolve: any, reject: any) => {
					fileReader.onload = (e: any) => {
						tempFile.url = e.target.result;
						resolve(true);
					};
					fileReader.readAsDataURL(blob);
				}).then((response: any) => {
					return tempFile;
				});
			} else {
				return tempFile;
			}
		} else {
			console.error(response);
		}
	} catch (error) {
		console.error(error);
	}
};

//下载文件
const downLoadFile = async (item: any) => {
	let tempItem = JSON.parse(JSON.stringify(item));
	const tempUrl = getDownloadUrl();
	const url = `${tempUrl}/${item.id}`;

	try {
		const response = await Http.getHttp()({
			method: 'get',
			url: url,
			responseType: 'blob',
		});
		if (!response || response.status != 200) {
			App.getNotificationHelper().warning(tempItem._url);
			return;
		}
		// 请求成功，后台返回的是一个文件流
		if (response.data) {
			// 获取文件名
			const filename = tempItem.name;
			const ext = '.' + filename.split('.').pop();
			let filetype = calcFilemime(ext);
			// 用blob对象获取文件流
			let blob = new Blob([response.data], { type: filetype });
			// 通过文件流创建下载链接
			var href = URL.createObjectURL(blob);
			// 创建一个a元素并设置相关属性
			let a = document.createElement('a');
			a.href = href;
			a.download = filename;
			// 添加a元素到当前网页
			document.body.appendChild(a);
			// 触发a元素的点击事件，实现下载
			a.click();
			// 从当前网页移除a元素
			document.body.removeChild(a);
			// 释放blob对象
			URL.revokeObjectURL(href);
		} else {
			console.error(response);
		}
	} catch (error) {
		console.error(error);
	}
};

//拼接上传地址或下载地址及其对应参数
const formatUrlParam = (url: string, params: IParam) => {
	const length = Object.keys(params).length;
	if (length > 0) {
		let _url = url + '?';
		Object.keys(params).forEach((item, index) => {
			_url += `${item}=${params[item]}`;
			if (index < length - 1) {
				_url += '&';
			}
		});
		return _url;
	}
	return url;
};

//判断是否为图片文件
const isImage = (filetype: string) => {
	const imageTypes = ['image/jpeg', 'image/gif', 'image/png', 'image/bmp'];
	if (imageTypes.indexOf(filetype) > -1) {
		return true;
	} else {
		return false;
	}
};

watch(
	() => props.value,
	(newVal: any, oldVal: any) => {
		if (newVal) {
			try {
				if (Array.isArray(newVal)) {
					const fileList = newVal.map((item: any) => {
						return {
							id: item[objectIdField || 'id'],
							name: item[objectNameField || 'name'],
						};
					});
					handleExportUrlParams(fileList);
				} else if (typeof newVal === 'string') {
					handleExportUrlParams(JSON.parse(newVal));
				} else {
					const item = {
						id: newVal[objectIdField || 'id'],
						name: newVal[objectNameField || 'name'],
					};
					handleExportUrlParams([item]);
				}
			} catch (error: any) {
				fileList.value = [];
			}
		} else {
			fileList.value = [];
		}
	},
	{ immediate: true }
);
</script>
